﻿#include "framelesswidget.h"
#include <QtMath>
#include <QIcon>
#include <QMenu>
#include <QEvent>
#include <QLabel>
#include <QtDebug>
#include <QPixmap>
#include <QPainter>
#include <QMenuBar>
#include <QHBoxLayout>
#include <QHoverEvent>
#include <QPushButton>
#include <QTableWidget>
#include <QOperatingSystemVersion>
#include <QGraphicsDropShadowEffect>
#include <QApplication>
#include <QDesktopWidget>
#include <QTimer>



FramelessWidget::FramelessWidget(QWidget *parent) : QWidget(parent)
{
    padding = 8;
    moveEnable = true;
    resizeEnable = true;

    pressed = false;
    pressedLeft = false;
    pressedRight = false;
    pressedTop = false;
    pressedBottom = false;
    pressedLeftTop = false;
    pressedRightTop = false;
    pressedLeftBottom = false;
    pressedRightBottom = false;

    setWindowIcon(QIcon(":/pic/icon.png"));

    initUi();
}

FramelessWidget::~FramelessWidget()
{
    qDebug() << QStringLiteral("被析构了");
}

bool FramelessWidget::eventFilter(QObject *watched, QEvent *event)
{
    if (event->type() == QEvent::Resize)
    {
        int width = this->width();
        int height = this->height();

        //左侧描点区域
        rectLeft = QRect(0, padding, padding, height - padding * 2);
        //上侧描点区域
        rectTop = QRect(padding, 0, width - padding * 2, padding);
        //右侧描点区域
        rectRight = QRect(width - padding, padding, padding, height - padding * 2);
        //下侧描点区域
        rectBottom = QRect(padding, height - padding, width - padding * 2, padding);

        //左上角描点区域
        rectLeftTop = QRect(0, 0, padding, padding);
        //右上角描点区域
        rectRightTop = QRect(width - padding, 0, padding, padding);
        //左下角描点区域
        rectLeftBottom = QRect(0, height - padding, padding, padding);
        //右下角描点区域
        rectRightBottom = QRect(width - padding, height - padding, padding, padding);
    }
    else if (event->type() == QEvent::HoverMove)
    {
        QHoverEvent *hoverEvent = dynamic_cast<QHoverEvent *>(event);
        QPoint point = hoverEvent->pos();

        if (resizeEnable)
        {
            if (rectLeft.contains(point))
            {
                this->setCursor(Qt::SizeHorCursor);
            }
            else if (rectRight.contains(point))
            {
                this->setCursor(Qt::SizeHorCursor);
            }
            else if (rectTop.contains(point))
            {
                this->setCursor(Qt::SizeVerCursor);
            }
            else if (rectBottom.contains(point))
            {
                this->setCursor(Qt::SizeVerCursor);
            }
            else if (rectLeftTop.contains(point))
            {
                this->setCursor(Qt::SizeFDiagCursor);
            }
            else if (rectRightTop.contains(point))
            {
                this->setCursor(Qt::SizeBDiagCursor);
            }
            else if (rectLeftBottom.contains(point))
            {
                this->setCursor(Qt::SizeBDiagCursor);
            }
            else if (rectRightBottom.contains(point))
            {
                this->setCursor(Qt::SizeFDiagCursor);
            }
            else
            {
                this->setCursor(Qt::ArrowCursor);
            }
        }

        //根据当前鼠标位置,计算XY轴移动了多少
        int offsetX = point.x() - lastPos.x();
        int offsetY = point.y() - lastPos.y();

        //当前最大&拖动距离大于20
        if (pressed)
        {
            QPoint distance = point - lastPos;
            int length = distance.manhattanLength();
            if (length > 20)
            {
                if(this->isMaximized())
                {   //! 最大化-->恢复初始状态
                    QRect rect = this->normalGeometry();
                    int desX = lastPos.x() * rect.width() / this->geometry().width();
                    int desY = lastPos.y();
                    rect.moveTopLeft(point - QPoint(desX, desY));
//                    this->setGeometry(rect);
                    lastPos = QPoint(desX, desY);
                    setZeroMargin(false);
                    this->showNormal();

                    m_windowState = DefaultWindow;

                    moveEnable   = true;
                    resizeEnable = true;
                }
                else if(m_windowState == LeftHalfWindow || m_windowState == RightHalfWindow)
                {   //! 半屏-->恢复初始状态
                    int desX = lastPos.x() * m_lastRect.width() / this->geometry().width();
                    int desY = lastPos.y();
                    m_lastRect.moveTopLeft(point - QPoint(desX, desY));
                    this->setGeometry(m_lastRect);
                    m_windowState = DefaultWindow;

                    moveEnable   = true;
                    resizeEnable = true;
                }
            }
        }


        if (moveEnable)
        {
            if (pressed)
            {
                /*TODO.2
                QRect _rect = QApplication::desktop()->availableGeometry();

                if (_rect.width() - mapToGlobal(point).x() < 10)
                {
                    if (!m_baseWidget->m_bHelpWidhetShow)
                    {
                        m_bubbleWidget->setMagicPoint(point+pos());

                        m_baseWidget->startAnimation(this->geometry(), QRect(_rect.width() / 2, 0, _rect.width() / 2, _rect.height()));
                        m_windowState = RightHalfWindow;
                        setZeroMargin(true);
                    }
                }
                else if (mapToGlobal(point).x() < 10)
                {
                    if (!m_baseWidget->m_bHelpWidhetShow)
                    {
                        m_bubbleWidget->setMagicPoint(point+pos());

                        m_baseWidget->startAnimation(this->geometry(), QRect(0, 0, _rect.width() / 2, _rect.height()));
                        m_windowState = LeftHalfWindow;
                        setZeroMargin(true);
                    }
                }
                else if (mapToGlobal(point).y() < 10)
                {
                    if (!m_baseWidget->m_bHelpWidhetShow)
                    {
                        m_bubbleWidget->setMagicPoint(point+pos());

                        m_baseWidget->startAnimation(this->geometry(), QRect(0, 0, _rect.width(), _rect.height()));
                        m_windowState = MaximumWindow;
                        setZeroMargin(true);
                    }
                }
                else
                {
                    m_baseWidget->hide();
                    setZeroMargin(false);
                }
                */





                //! 限制不能拖到屏幕底部之外
                int height = QApplication::desktop()->availableGeometry().height();
                if(mapToGlobal(point).y() >= height)
                    offsetY = 0;
                this->move(this->x() + offsetX, this->y() + offsetY);
            }
        }

        if (resizeEnable)
        {
            if (pressedLeft)
            {
                int resizeW = this->width() - offsetX;
                if (this->minimumWidth() <= resizeW)
                {
                    this->setGeometry(this->x() + offsetX, rectY, resizeW, rectH);
                }
            }
            else if (pressedRight)
            {
                this->setGeometry(rectX, rectY, rectW + offsetX, rectH);
            }
            else if (pressedTop)
            {
                int resizeH = this->height() - offsetY;
                if (this->minimumHeight() <= resizeH)
                {
                    this->setGeometry(rectX, this->y() + offsetY, rectW, resizeH);
                }
            }
            else if (pressedBottom)
            {
                this->setGeometry(rectX, rectY, rectW, rectH + offsetY);
            }
            else if (pressedLeftTop)
            {
                int resizeW = this->width() - offsetX;
                int resizeH = this->height() - offsetY;
                if (this->minimumWidth() <= resizeW)
                {
                    this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
                }
                if (this->minimumHeight() <= resizeH)
                {
                    this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
                }
            }
            else if (pressedRightTop)
            {
                int resizeW = rectW + offsetX;
                int resizeH = this->height() - offsetY;
                if (this->minimumHeight() <= resizeH)
                {
                    this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
                }
            }
            else if (pressedLeftBottom)
            {
                int resizeW = this->width() - offsetX;
                int resizeH = rectH + offsetY;
                if (this->minimumWidth() <= resizeW)
                {
                    this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
                }
                if (this->minimumHeight() <= resizeH)
                {
                    this->setGeometry(this->x(), this->y(), resizeW, resizeH);
                }
            }
            else if (pressedRightBottom)
            {
                int resizeW = rectW + offsetX;
                int resizeH = rectH + offsetY;
                this->setGeometry(this->x(), this->y(), resizeW, resizeH);
            }
        }
    }
    else if (event->type() == QEvent::MouseButtonPress)
    {
        QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent *>(event);
        if(mouseEvent->button() != Qt::LeftButton)
            return QObject::eventFilter(watched, event);

        rectX = this->x();
        rectY = this->y();
        rectW = this->width();
        rectH = this->height();
        lastPos = mouseEvent->pos();

        //判断按下的区域位置
        if (rectLeft.contains(lastPos))
        {
            pressedLeft = true;
        }
        else if (rectRight.contains(lastPos))
        {
            pressedRight = true;
        }
        else if (rectTop.contains(lastPos))
        {
            pressedTop = true;
        }
        else if (rectBottom.contains(lastPos))
        {
            pressedBottom = true;
        }
        else if (rectLeftTop.contains(lastPos))
        {
            pressedLeftTop = true;
        }
        else if (rectRightTop.contains(lastPos))
        {
            pressedRightTop = true;
        }
        else if (rectLeftBottom.contains(lastPos))
        {
            pressedLeftBottom = true;
        }
        else if (rectRightBottom.contains(lastPos))
        {
            pressedRightBottom = true;
        }
        else
        {
            if(mouseEvent->pos().y() > 38)
                return QObject::eventFilter(watched, event);

            pressed = true;
        }
    }
    else if (event->type() == QEvent::MouseMove)
    {
        //已用HoverMove处理
        if(this->isMaximized())
        {
        }
        else
        {
        }
    }
    else if (event->type() == QEvent::MouseButtonRelease)
    {
        pressed = false;
        pressedLeft = false;
        pressedRight = false;
        pressedTop = false;
        pressedBottom = false;
        pressedLeftTop = false;
        pressedRightTop = false;
        pressedLeftBottom = false;
        pressedRightBottom = false;
        this->setCursor(Qt::ArrowCursor);

        /*TODO.3
        if (m_baseWidget->m_bHelpWidhetShow)
        {
            switch (m_windowState) {
            case DefaultWindow:
                moveEnable   = true;
                resizeEnable = true;
                break;
            case LeftHalfWindow:
            case RightHalfWindow:
                m_lastRect = this->geometry();
                this->setGeometry(m_baseWidget->m_endRect);
                moveEnable   = false;
                resizeEnable = false;
                break;
            case MaximumWindow:
                this->showMaximized();
                moveEnable   = false;
                resizeEnable = false;
                setZeroMargin(true);
                break;
            }
        }

        m_baseWidget->stopAnimation();
        */
    }
    else if(event->type() == QEvent::MouseButtonDblClick)
    {
        QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent *>(event);
        if(mouseEvent->pos().y() > 38)
            return QObject::eventFilter(watched, event);

        if(this->isMaximized())
        {
            setZeroMargin(false);
            this->showNormal();
            moveEnable = true;
            resizeEnable = true;
            pressed = false;
        }
        else
        {
            setZeroMargin(true);
            this->showMaximized();
            moveEnable = false;
            resizeEnable = false;
            pressed = false;
        }
    }

    return QObject::eventFilter(watched, event);
}

bool FramelessWidget::tryMoveWidget(QMouseEvent* event)
{


 return false;
}

void FramelessWidget::setPadding(int padding)
{
    this->padding = padding;
}

void FramelessWidget::setMoveEnable(bool moveEnable)
{
    this->moveEnable = moveEnable;
}

void FramelessWidget::setResizeEnable(bool resizeEnable)
{
    this->resizeEnable = resizeEnable;
}

void FramelessWidget::setCenterWidget(QWidget *widget)
{
    int widgetCount = m_vBoxLayout1->count();
    for(int i = widgetCount - 1; i >= 0; --i)
    {
        QWidget *w = m_vBoxLayout1->itemAt(i)->widget();
        m_vBoxLayout1->removeWidget(w);
        delete w;
    }
    m_centerWidget = widget;
    m_vBoxLayout1->addWidget(widget);
    setMinimumSize(widget->width()+ 16, widget->height()+38+16);//! 标题高38,边框为8
}

void FramelessWidget::setZeroMargin(bool flag)
{
    if(flag)
    {
        m_vBoxLayout->setMargin(0);
    }
    else
    {
        m_vBoxLayout->setMargin(6);
    }
    this->update();
}

void FramelessWidget::initUi()
{
    setMouseTracking(true);
    installEventFilter(this);
    setAttribute(Qt::WA_Hover, true);
    setAttribute(Qt::WA_DeleteOnClose, true);

    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
    setAttribute(Qt::WA_TranslucentBackground);
#ifndef USE_LOCAL_PAINT
    QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect();
    effect->setBlurRadius(20);
    effect->setColor(QColor::fromRgbF(0, 0, 0, 0.7));
    effect->setOffset(0, 0);
    setGraphicsEffect(effect);
#endif


    m_vBoxLayout  = new QVBoxLayout(this);
    m_headerFrame = new QFrame(this);
    m_headerFrame->setObjectName("frame_header");
    m_headerFrame->setStyleSheet("#frame_header{background-color:pink}");
    m_hBoxLayout  = new QHBoxLayout(m_headerFrame);
    m_vBoxLayout1 = new QVBoxLayout;
    m_vBoxLayout->setMargin(8);
    m_hBoxLayout->setMargin(0);
    m_vBoxLayout1->setMargin(0);
    m_vBoxLayout->setSpacing(0);
    m_hBoxLayout->setSpacing(0);
    m_vBoxLayout1->setSpacing(0);
    m_headerFrame->setLayout(m_hBoxLayout);
    m_headerFrame->setFixedHeight(30);
    m_vBoxLayout->addWidget(m_headerFrame);
    m_vBoxLayout->addLayout(m_vBoxLayout1);
    setLayout(m_vBoxLayout);

    QLabel *logo = new QLabel(this);
    logo->setObjectName("label_logo");
    logo->setFixedSize(53, 38);
    logo->setStyleSheet("QLabel#label_logo { border-image:url(:/pic/icon.png); background-color: transparent; }");

    QSpacerItem *spacerItem = new QSpacerItem(200, 10, QSizePolicy::Expanding, QSizePolicy::Minimum);

    btn_min   = new QPushButton(this);
    btn_max   = new QPushButton(this);
    btn_close = new QPushButton(this);
    btn_min->setFixedSize(25, 38);
    btn_max->setFixedSize(25, 38);
    btn_close->setFixedSize(25, 38);

    connect(btn_min,   &QPushButton::clicked, [=](){ this->showMinimized(); });
    connect(btn_max,   &QPushButton::clicked, [=](){
        if(this->isMaximized())
        {
            setZeroMargin(false);
            this->showNormal();
            moveEnable = true;
            resizeEnable = true;
        }
        else
        {
            setZeroMargin(true);
            this->showMaximized();
            moveEnable = false;
            resizeEnable = false;
        }
    });

    connect(btn_close, &QPushButton::clicked, [=](){
        emit sigClose();
    });

    m_hBoxLayout->addWidget(logo);
    m_hBoxLayout->addItem(spacerItem);
    m_hBoxLayout->addWidget(btn_min);
    m_hBoxLayout->addWidget(btn_max);
    m_hBoxLayout->addWidget(btn_close);

    //![0] 这里添加一个默认的widget，用于显示
    QTableWidget *t = new QTableWidget();
    //t->setMinimumSize(800, 600);
    m_vBoxLayout1->addWidget(t);
    //setMinimumSize(t->size());
    //![0]
}

#ifdef USE_LOCAL_PAINT
void FramelessWidget::paintEvent(QPaintEvent *event)
{
    if (isMaximized())
    {
        return;
    }
    if(QOperatingSystemVersion::current() <= QOperatingSystemVersion::Windows7)//版本小于等于win7
    {
        m_vBoxLayout->setMargin(1);

        int nOffset = 0;
        int nShadowsWidth = 1;
        QPainterPath path;
        path.setFillRule(Qt::WindingFill);
        path.addRect(nShadowsWidth, nShadowsWidth, this->width() - nShadowsWidth * 2, this->height() - nShadowsWidth * 2);
        QPainter painter(this);
        QColor color("black");
        for (int i = 0; i < nShadowsWidth; i++)
        {
            QPainterPath path;
            path.setFillRule(Qt::WindingFill);
            path.addRect(nShadowsWidth - i + nOffset, nShadowsWidth - i + nOffset, this->width() - (nShadowsWidth - i) * 2, this->height() - (nShadowsWidth - i) * 2);
            painter.setPen(color);
            painter.drawPath(path);
        }
    }
    else
    {
        int nOffset = 0;
        int nShadowsWidth = 8;
        QPainterPath path;
        path.setFillRule(Qt::WindingFill);
        path.addRect(nShadowsWidth, nShadowsWidth, this->width() - nShadowsWidth * 2, this->height() - nShadowsWidth * 2);
        QPainter painter(this);
        QColor color(0, 0, 0, 200);
        for (int i = 0; i < nShadowsWidth; i++)
        {
            QPainterPath path;
            path.setFillRule(Qt::WindingFill);
            path.addRect(nShadowsWidth - i + nOffset, nShadowsWidth - i + nOffset, this->width() - (nShadowsWidth - i) * 2, this->height() - (nShadowsWidth - i) * 2);
            int alpha = static_cast<int>(100 - qSqrt(i) * 50);
            if(alpha < 0)
                alpha = 0;
            color.setAlpha(alpha);
            painter.setPen(color);
            painter.drawPath(path);
        }
    }
}
#endif
